from flask import Flask, request, jsonify, send_file
from flask_socketio import SocketIO, emit
from flask_cors import CORS
import os
import json
from datetime import datetime, timedelta
import random
import io
import csv
import threading
import time
import logging

# 配置日志
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('app.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger('wind_speed_monitor')

app = Flask(__name__)
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")

# 内存数据存储
stations = {
    'A': {'name': '站点A', 'location': '北部山区', 'status': 'online'},
    'B': {'name': '站点B', 'location': '南部平原', 'status': 'online'},
    'C': {'name': '站点C', 'location': '东部海岸', 'status': 'warning'},
    'D': {'name': '站点D', 'location': '西部沙漠', 'status': 'online'}
}

# 模拟数据
station_data = {}
thresholds = {'default': 12.0}  # 默认风速阈值
connected_clients = set()  # 记录连接的客户端

# 初始化模拟数据
def initialize_data():
    logger.info("初始化模拟数据")
    now = datetime.now()
    for station_id in stations:
        data = []
        # 生成7天的数据
        for i in range(168, 0, -1):  # 7天 * 24小时 = 168小时
            timestamp = now - timedelta(hours=i)
            base_wind = 8 if station_id == 'A' else 6 if station_id == 'B' else 10 if station_id == 'C' else 7
            data.append({
                'timestamp': timestamp.isoformat(),
                'windSpeed': round(base_wind + random.uniform(-3, 3), 1),
                'temperature': round(20 + random.uniform(-5, 5), 1),
                'humidity': round(65 + random.uniform(-15, 15))
            })
        station_data[station_id] = data
    logger.info(f"已为{len(stations)}个站点生成模拟数据")

# 获取所有站点
@app.route('/api/stations', methods=['GET'])
def get_stations():
    logger.debug("API请求: 获取所有站点")
    response = {
        'success': True,
        'stations': stations
    }
    logger.debug(f"响应数据: {response}")
    return jsonify(response)

# 获取特定站点信息
@app.route('/api/stations/<station_id>', methods=['GET'])
def get_station(station_id):
    logger.debug(f"API请求: 获取站点信息 {station_id}")
    if station_id not in stations:
        logger.warning(f"站点不存在: {station_id}")
        return jsonify({'success': False, 'error': 'Station not found'}), 404
    
    response = {
        'success': True,
        'station': stations[station_id]
    }
    logger.debug(f"响应数据: {response}")
    return jsonify(response)

# 获取站点数据
@app.route('/api/stations/<station_id>/data', methods=['GET'])
def get_station_data(station_id):
    logger.debug(f"API请求: 获取站点数据 {station_id}")
    if station_id not in station_data:
        logger.warning(f"站点数据不存在: {station_id}")
        return jsonify({'success': False, 'error': 'Station data not found'}), 404
    
    # 支持时间范围过滤
    hours = request.args.get('hours', '24')
    try:
        hours = int(hours)
    except ValueError:
        hours = 24
    
    logger.debug(f"请求时间范围: {hours}小时")
    filtered_data = station_data[station_id][-hours:] if hours < len(station_data[station_id]) else station_data[station_id]
    
    # 检查数据是否为空
    if not filtered_data:
        logger.warning(f"站点{station_id}在{hours}小时内没有数据")
    else:
        logger.debug(f"站点{station_id}有{len(filtered_data)}条数据记录")
        logger.debug(f"站点{station_id}最新风速: {filtered_data[-1]['windSpeed']}")
    
    response = {
        'success': True,
        'data': filtered_data
    }
    return jsonify(response)

# 获取多站点比较数据
@app.route('/api/comparison', methods=['GET'])
def get_comparison_data():
    station_ids = request.args.get('stations', '').split(',')
    hours = int(request.args.get('hours', '24'))
    
    result = {}
    for station_id in station_ids:
        if station_id in station_data:
            result[station_id] = station_data[station_id][-hours:] if hours < len(station_data[station_id]) else station_data[station_id]
    
    return jsonify({
        'success': True,
        'data': result
    })

# 设置风速阈值
@app.route('/api/thresholds', methods=['POST'])
def set_threshold():
    data = request.get_json()
    threshold = data.get('threshold')
    user_id = request.headers.get('Authorization', 'default')
    
    if threshold is None:
        return jsonify({'success': False, 'error': 'Missing threshold value'})
    
    thresholds[user_id] = float(threshold)
    
    return jsonify({
        'success': True,
        'threshold': thresholds[user_id]
    })

# 获取风速阈值
@app.route('/api/thresholds', methods=['GET'])
def get_threshold():
    user_id = request.headers.get('Authorization', 'default')
    return jsonify({
        'success': True,
        'threshold': thresholds.get(user_id, thresholds['default'])
    })

# 导出数据
@app.route('/api/export/<station_id>', methods=['GET'])
def export_data(station_id):
    if station_id not in station_data:
        return jsonify({'success': False, 'error': 'Station data not found'}), 404
    
    format_type = request.args.get('format', 'csv').lower()
    hours = int(request.args.get('hours', '168'))
    
    data = station_data[station_id][-hours:] if hours < len(station_data[station_id]) else station_data[station_id]
    
    if format_type == 'json':
        return jsonify(data)
    elif format_type == 'csv':
        output = io.StringIO()
        writer = csv.writer(output)
        writer.writerow(['时间戳', '风速(m/s)', '温度(°C)', '湿度(%)'])
        for item in data:
            writer.writerow([item['timestamp'], item['windSpeed'], item['temperature'], item['humidity']])
        
        mem = io.BytesIO()
        mem.write(output.getvalue().encode('utf-8'))
        mem.seek(0)
        output.close()
        
        return send_file(
            mem,
            mimetype='text/csv',
            as_attachment=True,
            download_name=f'风速数据_站点{station_id}_{datetime.now().strftime("%Y%m%d")}.csv'
        )
    else:
        return jsonify({'success': False, 'error': 'Unsupported format'}), 400

# 提供静态文件
@app.route('/')
def index():
    return send_file('../frontend/index.html')

@app.route('/<path:path>')
def serve_static(path):
    try:
        return send_file(f'../frontend/{path}')
    except:
        return "File not found", 404

# WebSocket连接事件
@socketio.on('connect')
def handle_connect():
    client_id = request.sid
    connected_clients.add(client_id)
    logger.info(f"客户端已连接: {client_id}, 总客户端数: {len(connected_clients)}")

@socketio.on('disconnect')
def handle_disconnect():
    client_id = request.sid
    if client_id in connected_clients:
        connected_clients.remove(client_id)
    logger.info(f"客户端已断开: {client_id}, 总客户端数: {len(connected_clients)}")

# 生成并推送最新数据
def push_latest_data():
    now = datetime.now()
    updates = {}
    
    for station_id in stations:
        # 生成新数据点
        base_wind = 8 if station_id == 'A' else 6 if station_id == 'B' else 10 if station_id == 'C' else 7
        
        # 添加一些随机变化和趋势
        hour_of_day = now.hour
        # 白天风速略高
        time_factor = 1.2 if 8 <= hour_of_day <= 18 else 0.8
        
        # 更新站点状态
        new_wind_speed = round(base_wind * time_factor + random.uniform(-3, 3), 1)
        if new_wind_speed > thresholds['default']:
            stations[station_id]['status'] = 'warning'
        else:
            stations[station_id]['status'] = 'online'
        
        new_data = {
            'timestamp': now.isoformat(),
            'windSpeed': new_wind_speed,
            'temperature': round(20 + random.uniform(-5, 5), 1),
            'humidity': round(65 + random.uniform(-15, 15))
        }
        
        # 添加到历史数据
        if station_id in station_data:
            station_data[station_id].append(new_data)
            # 保持7天的数据量
            if len(station_data[station_id]) > 168:
                station_data[station_id].pop(0)
        else:
            # 如果站点数据不存在，则创建
            logger.warning(f"站点{station_id}数据不存在，正在创建")
            station_data[station_id] = [new_data]
            
        updates[station_id] = new_data
        logger.debug(f"已生成站点{station_id}的新数据: 风速={new_wind_speed}m/s")
        
        # 检查是否超过阈值，发送警报
        if new_data['windSpeed'] > thresholds['default']:
            socketio.emit('alert', {
                'station': station_id,
                'type': 'danger',
                'message': f'站点{station_id}: 风速超过阈值 ({new_data["windSpeed"]}m/s)',
                'timestamp': now.isoformat()
            })
            logger.warning(f"站点{station_id}风速超过阈值: {new_data['windSpeed']}m/s")
        elif new_data['windSpeed'] > thresholds['default'] * 0.8:
            socketio.emit('alert', {
                'station': station_id,
                'type': 'warning',
                'message': f'站点{station_id}: 风速接近阈值 ({new_data["windSpeed"]}m/s)',
                'timestamp': now.isoformat()
            })
            logger.info(f"站点{station_id}风速接近阈值: {new_data['windSpeed']}m/s")
    
    # 广播最新数据
    socketio.emit('data_update', updates)
    logger.info(f"数据已更新 - {now.strftime('%Y-%m-%d %H:%M:%S')}, 在线客户端: {len(connected_clients)}")
    logger.debug(f"推送的数据更新: {updates}")

# 数据推送线程函数
def data_pusher_thread():
    while True:
        # 只在有客户端连接时推送数据
        if connected_clients:
            try:
                push_latest_data()
            except Exception as e:
                logger.error(f"推送数据时出错: {e}")
        
        # 每30秒更新一次数据
        time.sleep(30)

# 启动后台线程
def start_background_tasks():
    # 初始化数据
    initialize_data()
    logger.info("初始化数据完成")
    
    # 启动数据推送线程
    thread = threading.Thread(target=data_pusher_thread)
    thread.daemon = True
    thread.start()
    logger.info("后台数据推送线程已启动")

if __name__ == '__main__':
    # 确保在直接运行时也初始化数据
    initialize_data()
    logger.info("应用启动，数据已初始化")
    
    # 启动数据推送线程
    thread = threading.Thread(target=data_pusher_thread)
    thread.daemon = True
    thread.start()
    logger.info("后台数据推送线程已启动")
    
    # 启动WebSocket服务器
    socketio.run(app, debug=True, host='0.0.0.0', port=5000)